home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / x / volume2 / x11.3 / patch3 < prev    next >
Encoding:
Text File  |  1988-12-12  |  28.4 KB  |  1,197 lines

  1. Path: uunet!wyse!mikew
  2. From: mikew@wyse.wyse.com (Mike Wexler)
  3. Newsgroups: comp.sources.x
  4. Subject: v02i043:  X11 Release 3, Patch3
  5. Message-ID: <1897@wyse.wyse.com>
  6. Date: 12 Dec 88 21:19:27 GMT
  7. Organization: Wyse Technology, San Jose
  8. Lines: 1186
  9. Approved: mikew@wyse.com
  10.  
  11. Submitted-by: Xstuff service <xstuff@EXPO.LCS.MIT.EDU>
  12. Posting-number: Volume 2, Issue 43
  13. Archive-name: x11.3/patch3
  14.  
  15.  
  16.  
  17. This patch optimizes some special cases in the mi arc code.  It
  18. affects only server/ddx/mi/miarc.c
  19.  
  20. Circular arcs are now computed specially with a direct equation, instead of
  21. using the more general elipse solution.
  22.  
  23. Memory allocation for span generation/merging was rewritten to reduce
  24. the number of small Xalloc calls.
  25.  
  26. Zero height/width arcs now use pGC->PolyFillRect instead of miSppFillPoly.
  27.  
  28. All of these changes are based on actual -pg style profiling results run on a
  29. Vaxstation 3200.
  30.  
  31. Circular arcs are now at least 20 times faster, Zero width/height arcs are
  32. at least 10 times faster on the 3200.  I expect more substantial changes on
  33. Suns which don't have floating point hardware, but have no data which
  34. demonstrates this.
  35.  
  36. *** /tmp/,RCSt1a15146    Fri Dec  9 13:27:24 1988
  37. --- server/ddx/mi/miarc.c    Fri Dec  9 13:26:39 1988
  38. ***************
  39. *** 21,27 ****
  40.   SOFTWARE.
  41.   
  42.   ******************************************************************/
  43. ! /* $XConsortium: miarc.c,v 1.63 88/10/23 17:07:31 keith Exp $ */
  44.   /* Author: Keith Packard */
  45.   
  46.   #include "X.h"
  47. --- 21,27 ----
  48.   SOFTWARE.
  49.   
  50.   ******************************************************************/
  51. ! /* $XConsortium: miarc.c,v 1.67 88/12/09 13:25:56 keith Exp $ */
  52.   /* Author: Keith Packard */
  53.   
  54.   #include "X.h"
  55. ***************
  56. *** 34,39 ****
  57. --- 34,63 ----
  58.   #include "mifpoly.h"
  59.   #include "mi.h"
  60.   
  61. + /*
  62. +  * some interesting sematic interpretation of the protocol:
  63. +  *
  64. +  * Self intersecting arcs (i.e. those spanning 360 degrees) 
  65. +  *  never join with other arcs, and are drawn without caps
  66. +  *  (unless on/off dashed, in which case each dash segment
  67. +  *  is capped, except when the last segment meets the
  68. +  *  first segment, when no caps are drawn)
  69. +  *
  70. +  * double dash arcs are drawn in two parts, first the
  71. +  *  odd dashes (drawn in background) then the even dashes
  72. +  *  (drawn in foreground).  This means that overlapping
  73. +  *  sections of foreground/background are drawn twice,
  74. +  *  first in background then in foreground.  The double-draw
  75. +  *  occurs even when the function uses the destination values
  76. +  *  (e.g. xor mode).  This is the same way the wide-line
  77. +  *  code works and should be "fixed".
  78. +  *
  79. +  * the wide arc code will never be "correct" -- the protocol
  80. +  *  document specifies exact pixelization which is impossible
  81. +  *  when calculating pixel positions with complicated floating-
  82. +  *  point expressions.
  83. +  */
  84.   extern double sqrt(), cos(), sin(), atan();
  85.   
  86.   /* these are from our <math.h>, but I'm told some systems don't have
  87. ***************
  88. *** 72,91 ****
  89.       SppPointRec    counterClock;
  90.   } miArcFaceRec, *miArcFacePtr;
  91.   
  92. - /*
  93. -  * This is an entire sequence of arcs, computed and categorized according
  94. -  * to operation.  miDashArcs generates either one or two of these.
  95. -  */
  96.   typedef struct _miArcData {
  97.       xArc        arc;
  98.       int        render;        /* non-zero means render after drawing */
  99.       int        join;        /* related join */
  100.       int        cap;        /* related cap */
  101.       miArcFaceRec    bounds[2];
  102.       double        x0, y0, x1, y1;
  103.   } miArcDataRec, *miArcDataPtr;
  104.   
  105.   typedef struct _miPolyArc {
  106.       int        narcs;
  107.       miArcDataPtr    arcs;
  108. --- 96,116 ----
  109.       SppPointRec    counterClock;
  110.   } miArcFaceRec, *miArcFacePtr;
  111.   
  112.   typedef struct _miArcData {
  113.       xArc        arc;
  114.       int        render;        /* non-zero means render after drawing */
  115.       int        join;        /* related join */
  116.       int        cap;        /* related cap */
  117. +     int        selfJoin;    /* final dash meets first dash */
  118.       miArcFaceRec    bounds[2];
  119.       double        x0, y0, x1, y1;
  120.   } miArcDataRec, *miArcDataPtr;
  121.   
  122. + /*
  123. +  * This is an entire sequence of arcs, computed and categorized according
  124. +  * to operation.  miDashArcs generates either one or two of these.
  125. +  */
  126.   typedef struct _miPolyArc {
  127.       int        narcs;
  128.       miArcDataPtr    arcs;
  129. ***************
  130. *** 185,190 ****
  131. --- 210,216 ----
  132.    * from the scratch drawable to pDraw. (See the wide line code for a
  133.    * fuller explanation of this.)
  134.    */
  135.   void
  136.   miPolyArc(pDraw, pGC, narcs, parcs)
  137.       DrawablePtr    pDraw;
  138. ***************
  139. *** 316,321 ****
  140. --- 342,353 ----
  141.                    &arcData->bounds[LEFT_END]);
  142.           if (polyArcs[iphase].arcs[i].render) {
  143.               fillSpans (pDrawTo, pGCTo);
  144. +             /*
  145. +              * don't cap self-joining arcs
  146. +              */
  147. +             if (polyArcs[iphase].arcs[i].selfJoin &&
  148. +                 cap[iphase] < polyArcs[iphase].arcs[i].cap)
  149. +                 cap[iphase]++;
  150.               while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {
  151.               int    arcIndex, end;
  152.               miArcDataPtr    arcData0;
  153. ***************
  154. *** 874,879 ****
  155. --- 906,912 ----
  156.       xArc        xarc;
  157.       int        iphase, prevphase, joinphase;
  158.       int        arcsJoin;
  159. +     int        selfJoin;
  160.   
  161.       int        iDash, dashRemaining;
  162.       int        iDashStart, dashRemainingStart, iphaseStart;
  163. ***************
  164. *** 937,943 ****
  165.           j = i + 1;
  166.           if (j == narcs)
  167.               j = 0;
  168. !         if (!data[i].selfJoin && 
  169.                (UNEQUAL (data[i].x1, data[j].x0) ||
  170.                 UNEQUAL (data[i].y1, data[j].y0)))
  171.            {
  172. --- 970,976 ----
  173.           j = i + 1;
  174.           if (j == narcs)
  175.               j = 0;
  176. !         if (data[i].selfJoin || 
  177.                (UNEQUAL (data[i].x1, data[j].x0) ||
  178.                 UNEQUAL (data[i].y1, data[j].y0)))
  179.            {
  180. ***************
  181. *** 959,964 ****
  182. --- 992,1001 ----
  183.           if (nexti == narcs)
  184.               nexti = 0;
  185.           if (isDashed) {
  186. +             /*
  187. +              * compute each individual dash segment using the path
  188. +              * length function
  189. +              */
  190.               startAngle = parcs[i].angle1;
  191.               spanAngle = parcs[i].angle2;
  192.               if (spanAngle > FULLCIRCLE)
  193. ***************
  194. *** 972,977 ****
  195. --- 1009,1016 ----
  196.               endAngle = startAngle + spanAngle;
  197.               backwards = spanAngle < 0;
  198.               prevDashAngle = startAngle;
  199. +             selfJoin = data[i].selfJoin &&
  200. +                      (iphase == 0 || isDoubleDash);
  201.               while (prevDashAngle != endAngle) {
  202.                   dashAngle = computeAngleFromPath
  203.                            (prevDashAngle, endAngle,
  204. ***************
  205. *** 992,997 ****
  206. --- 1031,1039 ----
  207.                       xarc.angle2 = spanAngle;
  208.                       arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
  209.                                &arcSize[iphase], xarc);
  210. +                     /*
  211. +                      * cap each end of an on/off dash
  212. +                      */
  213.                       if (!isDoubleDash) {
  214.                           if (prevDashAngle != startAngle) {
  215.                               addCap (&arcs[iphase].caps,
  216. ***************
  217. *** 1010,1015 ****
  218. --- 1052,1060 ----
  219.                       arc->cap = arcs[iphase].ncaps;
  220.                       arc->join = arcs[iphase].njoins;
  221.                       arc->render = 0;
  222. +                     arc->selfJoin = 0;
  223. +                     if (dashAngle == endAngle)
  224. +                         arc->selfJoin = selfJoin;
  225.                   }
  226.                   prevphase = iphase;
  227.                   if (dashRemaining <= 0) {
  228. ***************
  229. *** 1026,1031 ****
  230. --- 1071,1077 ----
  231.                          &arcSize[iphase], parcs[i]);
  232.               arc->join = arcs[iphase].njoins;
  233.               arc->cap = arcs[iphase].ncaps;
  234. +             arc->selfJoin = data[i].selfJoin;
  235.               prevphase = iphase;
  236.           }
  237.           if (prevphase == 0 || isDoubleDash)
  238. ***************
  239. *** 1042,1048 ****
  240.           }
  241.           arcsJoin = narcs > 1 && 
  242.                    ISEQUAL (data[i].x1, data[j].x0) &&
  243. !                 ISEQUAL (data[i].y1, data[j].y0);
  244.           if (arcsJoin)
  245.               arc->render = 0;
  246.           else
  247. --- 1088,1095 ----
  248.           }
  249.           arcsJoin = narcs > 1 && 
  250.                    ISEQUAL (data[i].x1, data[j].x0) &&
  251. !                 ISEQUAL (data[i].y1, data[j].y0) &&
  252. !                 !data[i].selfJoin && !data[j].selfJoin;
  253.           if (arcsJoin)
  254.               arc->render = 0;
  255.           else
  256. ***************
  257. *** 1074,1081 ****
  258.                   arc->join = arcs[prevphase].njoins;
  259.               }
  260.           } else {
  261.               if ((prevphase == 0 || isDoubleDash) &&
  262. !                 !data[i].selfJoin)
  263.               {
  264.                   addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps,
  265.                        &capSize[prevphase], LEFT_END, k);
  266. --- 1121,1132 ----
  267.                   arc->join = arcs[prevphase].njoins;
  268.               }
  269.           } else {
  270. +             /*
  271. +              * cap the left end of this arc
  272. +              * unless it joins itself
  273. +              */
  274.               if ((prevphase == 0 || isDoubleDash) &&
  275. !                 !arc->selfJoin)
  276.               {
  277.                   addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps,
  278.                        &capSize[prevphase], LEFT_END, k);
  279. ***************
  280. *** 1103,1110 ****
  281.                * hardly matters...
  282.                */
  283.               if ((iphase == 0 || isDoubleDash) &&
  284. !                 (nexti != start || arcsJoin && isDashed) &&
  285. !                  !data[j].selfJoin)
  286.                   addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
  287.                        &capSize[iphase], RIGHT_END, nextk);
  288.           }
  289. --- 1154,1160 ----
  290.                * hardly matters...
  291.                */
  292.               if ((iphase == 0 || isDoubleDash) &&
  293. !                 (nexti != start || arcsJoin && isDashed))
  294.                   addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
  295.                        &capSize[iphase], RIGHT_END, nextk);
  296.           }
  297. ***************
  298. *** 1288,1293 ****
  299. --- 1338,1348 ----
  300.       return a1;
  301.   }
  302.   
  303. + /*
  304. +  * To avoid inaccuracy at the cardinal points, use trig functions
  305. +  * which are exact for those angles
  306. +  */
  307.   # define Dsin(d)    ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
  308.   # define Dcos(d)    ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
  309.   
  310. ***************
  311. *** 1330,1338 ****
  312.   }
  313.   
  314.   /*
  315. !  * draw zero width/height arcs with the rectangle routines
  316.    */
  317.   
  318.   drawZeroArc (pDraw, pGC, tarc, left, right)
  319.       DrawablePtr   pDraw;
  320.       GCPtr         pGC;
  321. --- 1385,1403 ----
  322.   }
  323.   
  324.   /*
  325. !  * scan convert wide arcs.
  326.    */
  327.   
  328. + #undef fabs
  329. + #undef min
  330. + #undef max
  331. + extern double    ceil (), floor (), fabs (), sin (), cos (), sqrt (), pow ();
  332. + /*
  333. +  * draw zero width/height arcs
  334. +  */
  335.   drawZeroArc (pDraw, pGC, tarc, left, right)
  336.       DrawablePtr   pDraw;
  337.       GCPtr         pGC;
  338. ***************
  339. *** 1342,1348 ****
  340.       double    x0, y0, x1, y1, w, h;
  341.       int    a0, a1;
  342.       double    startAngle, endAngle;
  343. -     SppPointRec    box[4];
  344.       double    l;
  345.   
  346.       l = pGC->lineWidth;
  347. --- 1407,1412 ----
  348. ***************
  349. *** 1386,1401 ****
  350.           }
  351.       }
  352.       if (x1 != x0 && y1 != y0) {
  353. !         box[0].x = x0;
  354. !         box[0].y = y0;
  355. !         box[1].x = x1;
  356. !         box[1].y = y0;
  357. !         box[2].x = x1;
  358. !         box[2].y = y1;
  359. !         box[3].x = x0;
  360. !         box[3].y = y1;
  361. !         miFillSppPoly (pDraw, pGC, 4, box, tarc.x, tarc.y,
  362. !                    w, h);
  363.       }
  364.       if (right) {
  365.           if (h != 0) {
  366. --- 1450,1481 ----
  367.           }
  368.       }
  369.       if (x1 != x0 && y1 != y0) {
  370. !         int    minx, maxx, miny, maxy, y, t;
  371. !         xRectangle  rect;
  372. !         minx = ceil (x0 + w) + tarc.x;
  373. !         maxx = ceil (x1 + w) + tarc.x;
  374. !         if (minx > maxx) {
  375. !             t = minx;
  376. !             minx = maxx;
  377. !             maxx = t;
  378. !         }
  379. !         miny = ceil (y0 + h) + tarc.y;
  380. !         maxy = ceil (y1 + h) + tarc.y;
  381. !         if (miny > maxy) {
  382. !             t = miny;
  383. !             miny = maxy;
  384. !             maxy = t;
  385. !         }
  386. !         rect.x = minx;
  387. !         rect.y = miny;
  388. !         rect.width = maxx - minx;
  389. !         rect.height = maxy - miny;
  390. !         (*pGC->PolyFillRect) (pDraw, pGC, 1, &rect);
  391. ! /*
  392. !         for (y = miny; y < maxy; y++)
  393. !             newFinalSpan (y, minx, maxx);
  394. ! */
  395.       }
  396.       if (right) {
  397.           if (h != 0) {
  398. ***************
  399. *** 1433,1449 ****
  400.       }
  401.   }
  402.   
  403. -  
  404. - /*
  405. -  * scan convert wide arcs.
  406. -  */
  407. - #undef fabs
  408. - #undef min
  409. - #undef max
  410. - extern double    ceil (), floor (), fabs (), sin (), cos (), sqrt (), pow ();
  411.   # define BINARY_LIMIT    (0.1)
  412.   # define NEWTON_LIMIT    (0.0000001)
  413.   
  414. --- 1513,1518 ----
  415. ***************
  416. *** 1512,1530 ****
  417.       return a < b ? a : b;
  418.   }
  419.   
  420. ! boundedLt (value, bounds)
  421. ! double    value;
  422. ! struct bound    bounds;
  423. ! {
  424. !     return bounds.min <= value && value < bounds.max;
  425. ! }
  426.   
  427. ! boundedLe (value, bounds)
  428. ! double    value;
  429. ! struct bound    bounds;
  430. ! {
  431. !     return bounds.min <= value && value <= bounds.max;
  432. ! }
  433.   
  434.   /*
  435.    * this computes the elipse y value associated with the
  436. --- 1581,1591 ----
  437.       return a < b ? a : b;
  438.   }
  439.   
  440. ! #define boundedLt(value, bounds) \
  441. !     ((bounds).min <= (value) && (value) < (bounds).max)
  442.   
  443. ! #define boundedLe(value, bounds)\
  444. !     ((bounds).min <= (value) && (value) <= (bounds).max)
  445.   
  446.   /*
  447.    * this computes the elipse y value associated with the
  448. ***************
  449. *** 1673,1678 ****
  450. --- 1734,1745 ----
  451.       return line->m * y + line->b;
  452.   }
  453.   
  454. + /*
  455. +  * compute various accelerators for an elipse.  These
  456. +  * are simply values that are used repeatedly in
  457. +  * the computations
  458. +  */
  459.   computeAcc (def, acc)
  460.       struct arc_def        *def;
  461.       struct accelerators    *acc;
  462. ***************
  463. *** 1687,1692 ****
  464. --- 1754,1764 ----
  465.       acc->tail_y = tailElipseY (def->w, def->h, def->l);
  466.   }
  467.           
  468. + /*
  469. +  * compute y value bounds of various portions of the arc,
  470. +  * the outer edge, the elipse and the inner edge.
  471. +  */
  472.   computeBound (def, bound, acc, right, left)
  473.       struct arc_def        *def;
  474.       struct arc_bound    *bound;
  475. ***************
  476. *** 1721,1727 ****
  477.       
  478.       /*
  479.        * save the line end points for the
  480. !      * cap code to use
  481.        */
  482.   
  483.       if (right) {
  484. --- 1793,1802 ----
  485.       
  486.       /*
  487.        * save the line end points for the
  488. !      * cap code to use.  Careful here, these are
  489. !      * in cartesean coordinates (y increasing upwards)
  490. !      * while the cap code uses inverted coordinates
  491. !      * (y increasing downwards)
  492.        */
  493.   
  494.       if (right) {
  495. ***************
  496. *** 1772,1778 ****
  497.   /*
  498.    * using newtons method and a binary search, compute the elipse y value
  499.    * associated with the given edge value (either outer or
  500. !  * inner)
  501.    */
  502.   
  503.   double
  504. --- 1847,1881 ----
  505.   /*
  506.    * using newtons method and a binary search, compute the elipse y value
  507.    * associated with the given edge value (either outer or
  508. !  * inner).  This is the heart of the scan conversion code and
  509. !  * is generally called three times for each span.  It should
  510. !  * be optimized further.
  511. !  *
  512. !  * the general idea here is to solve the equation:
  513. !  *
  514. !  *                               w^2 * l
  515. !  *   edge_y = y + y * -------------------------------
  516. !  *                    2 * sqrt (x^2 * h^4 + y^2 * w^4)
  517. !  *
  518. !  * for y.  (x, y) is a point on the elipse, so x can be
  519. !  * found from y:
  520. !  *
  521. !  *                ( h^2 - y^2 )
  522. !  *   x = w * sqrt ( --------- )
  523. !  *                (    h^2    )
  524. !  *
  525. !  * The information given at the start of the search
  526. !  * is two points which are known to bound the desired
  527. !  * solution, a binary search starts with these two points
  528. !  * and converges close to a solution, which is then
  529. !  * refined with newtons method.  Newtons method
  530. !  * cannot be used in isolation as it does not always
  531. !  * converge to the desired solution without a close
  532. !  * starting point, the binary search simply provides
  533. !  * that point.  Increasing the solution interval for
  534. !  * the binary search will certainly speed up the
  535. !  * solution, but may generate a range which causes
  536. !  * the newtons method to fail.  This needs study.
  537.    */
  538.   
  539.   double
  540. ***************
  541. *** 1781,1794 ****
  542.       struct arc_def        *def;
  543.       struct arc_bound    *bound;
  544.       struct accelerators    *acc;
  545. !     double            y0, y1;
  546.   {
  547. !     double    w, h, l, h2, h4, w2, w4, x, y2;
  548. !     double    newtony, binaryy;
  549. !     double    value0, value1, valuealt;
  550. !     double    newtonvalue, binaryvalue;
  551. !     double    minY, maxY;
  552. !     double    (*f)();
  553.       
  554.       /*
  555.        * compute some accelerators
  556. --- 1884,1898 ----
  557.       struct arc_def        *def;
  558.       struct arc_bound    *bound;
  559.       struct accelerators    *acc;
  560. !     register double        y0, y1;
  561.   {
  562. !     register double    w, h, l, h2, h4, w2, w4, x, y2;
  563. !     double        newtony, binaryy;
  564. !     double        value0, value1, valuealt;
  565. !     double        newtonvalue, binaryvalue;
  566. !     double        minY, maxY;
  567. !     double        binarylimit;
  568. !     double        (*f)();
  569.       
  570.       /*
  571.        * compute some accelerators
  572. ***************
  573. *** 1816,1821 ****
  574. --- 1920,1928 ----
  575.           return y1;
  576.       if (value1 > 0 == value0 > 0)
  577.           return -1.0;    /* an illegal value */
  578. +     binarylimit = fabs ((value1 - value0) / 25.0);
  579. +     if (binarylimit < BINARY_LIMIT)
  580. +         binarylimit = BINARY_LIMIT;
  581.       /*
  582.        * binary search for a while
  583.        */
  584. ***************
  585. *** 1834,1841 ****
  586.           binaryvalue = ( binaryy + (binaryy * w2 * l) /
  587.                     (2 * Sqrt (x*x * h4 + y2 * w4))) - edge_y;
  588.   
  589. -         if (binaryvalue == 0)
  590. -             return binaryy;
  591.           if (binaryvalue > 0 == value0 > 0) {
  592.               y0 = binaryy;
  593.               value0 = binaryvalue;
  594. --- 1941,1946 ----
  595. ***************
  596. *** 1843,1849 ****
  597.               y1 = binaryy;
  598.               value1 = binaryvalue;
  599.           }
  600. !     } while (fabs (value1) > BINARY_LIMIT);
  601.   
  602.       /*
  603.        * clean up the estimate with newtons method
  604. --- 1948,1956 ----
  605.               y1 = binaryy;
  606.               value1 = binaryvalue;
  607.           }
  608. !     } while (fabs (value1) > binarylimit);
  609. !     if (binaryvalue == 0)
  610. !         return binaryy;
  611.   
  612.       /*
  613.        * clean up the estimate with newtons method
  614. ***************
  615. *** 1889,1901 ****
  616.   
  617.   double
  618.   outerX (outer_y, def, bound, acc)
  619. !     double            outer_y;
  620. !     struct arc_def        *def;
  621.       struct arc_bound    *bound;
  622.       struct accelerators    *acc;
  623.   {
  624.       double    y;
  625.   
  626.       if (outer_y == bound->outer.min)
  627.           y = bound->elipse.min;
  628.       if (outer_y == bound->outer.max)
  629. --- 1996,2018 ----
  630.   
  631.   double
  632.   outerX (outer_y, def, bound, acc)
  633. !     register double        outer_y;
  634. !     register struct arc_def    *def;
  635.       struct arc_bound    *bound;
  636.       struct accelerators    *acc;
  637.   {
  638.       double    y;
  639.   
  640. +     /*
  641. +      * special case for circles
  642. +      */
  643. +     if (def->w == def->h) {
  644. +         register double    x;
  645. +         x = def->w + def->l/2.0;
  646. +         x = Sqrt (x * x - outer_y * outer_y);
  647. +         return x;
  648. +     }
  649.       if (outer_y == bound->outer.min)
  650.           y = bound->elipse.min;
  651.       if (outer_y == bound->outer.max)
  652. ***************
  653. *** 1902,1908 ****
  654.           y = bound->elipse.max;
  655.       else
  656.           y = elipseY (outer_y, def, bound, acc, 1,
  657. !                   bound->elipse.min, bound->elipse.max, -1.0);
  658.       return outerXfromY (y, def, acc);
  659.   }
  660.   
  661. --- 2019,2025 ----
  662.           y = bound->elipse.max;
  663.       else
  664.           y = elipseY (outer_y, def, bound, acc, 1,
  665. !                   bound->elipse.min, bound->elipse.max);
  666.       return outerXfromY (y, def, acc);
  667.   }
  668.   
  669. ***************
  670. *** 1911,1924 ****
  671.    */
  672.   
  673.   innerXs (inner_y, def, bound, acc, innerX1p, innerX2p)
  674. !     double            inner_y;
  675.       struct arc_def        *def;
  676.       struct arc_bound    *bound;
  677.       struct accelerators    *acc;
  678.       double            *innerX1p, *innerX2p;
  679.   {
  680. !     double    x1, x2, xalt, y0, y1, altY, elipse_y1, elipse_y2;
  681.   
  682.       if (boundedLe (acc->tail_y, bound->elipse)) {
  683.           if (def->h > def->w) {
  684.               y0 = bound->elipse.min;
  685. --- 2028,2053 ----
  686.    */
  687.   
  688.   innerXs (inner_y, def, bound, acc, innerX1p, innerX2p)
  689. !     register double        inner_y;
  690.       struct arc_def        *def;
  691.       struct arc_bound    *bound;
  692.       struct accelerators    *acc;
  693.       double            *innerX1p, *innerX2p;
  694.   {
  695. !     register double    x1, x2;
  696. !     double        xalt, y0, y1, altY, elipse_y1, elipse_y2;
  697.   
  698. +     /*
  699. +      * special case for circles
  700. +      */
  701. +     if (def->w == def->h) {
  702. +         x1 = def->w - def->l/2.0;
  703. +         x2 = Sqrt (x1 * x1 - inner_y * inner_y);
  704. +         if (x1 < 0)
  705. +             x2 = -x2;
  706. +         *innerX1p = *innerX2p = x2;
  707. +         return;
  708. +     }
  709.       if (boundedLe (acc->tail_y, bound->elipse)) {
  710.           if (def->h > def->w) {
  711.               y0 = bound->elipse.min;
  712. ***************
  713. *** 2048,2068 ****
  714.       double    elipse_y, elipse_x, x, xalt;
  715.       double    maxMin;
  716.   
  717. !     elipse_y = hookElipseY (scan_y, def, bound, acc, left);
  718. !     if (boundedLe (elipse_y, bound->elipse)) {
  719. !         /*
  720. !          * compute the value of the second
  721. !          * derivative
  722. !          */
  723. !         maxMin = elipse_y*elipse_y*elipse_y * acc->h2mw2 -
  724. !          acc->h2 * scan_y * (3 * elipse_y*elipse_y - 2*acc->h2);
  725. !         if ((left && maxMin > 0) || (!left && maxMin < 0)) {
  726. !             if (elipse_y == 0)
  727. !                 return def->w + left ? -def->l/2 : def->l/2;
  728. !             x = (acc->h2 * scan_y - elipse_y * acc->h2mw2) *
  729. !                 Sqrt (acc->h2 - elipse_y * elipse_y) /
  730. !                  (def->h * def->w * elipse_y);
  731. !             return x;
  732.           }
  733.       }
  734.       if (left) {
  735. --- 2177,2199 ----
  736.       double    elipse_y, elipse_x, x, xalt;
  737.       double    maxMin;
  738.   
  739. !     if (def->w != def->h) {
  740. !         elipse_y = hookElipseY (scan_y, def, bound, acc, left);
  741. !         if (boundedLe (elipse_y, bound->elipse)) {
  742. !             /*
  743. !               * compute the value of the second
  744. !               * derivative
  745. !               */
  746. !             maxMin = elipse_y*elipse_y*elipse_y * acc->h2mw2 -
  747. !               acc->h2 * scan_y * (3 * elipse_y*elipse_y - 2*acc->h2);
  748. !             if ((left && maxMin > 0) || (!left && maxMin < 0)) {
  749. !                 if (elipse_y == 0)
  750. !                     return def->w + left ? -def->l/2 : def->l/2;
  751. !                 x = (acc->h2 * scan_y - elipse_y * acc->h2mw2) *
  752. !                     Sqrt (acc->h2 - elipse_y * elipse_y) /
  753. !                      (def->h * def->w * elipse_y);
  754. !                 return x;
  755. !             }
  756.           }
  757.       }
  758.       if (left) {
  759. ***************
  760. *** 2087,2092 ****
  761. --- 2218,2228 ----
  762.       return x;
  763.   }
  764.   
  765. + /*
  766. +  * generate the set of spans with
  767. +  * the given y coordinate
  768. +  */
  769.   arcSpan (y, def, bounds, acc)
  770.       double            y;
  771.       struct arc_def        *def;
  772. ***************
  773. *** 2159,2174 ****
  774.       int            min, max;    /* x values */
  775.   };
  776.   
  777.   fillSpans (pDrawable, pGC)
  778.       DrawablePtr    pDrawable;
  779.       GCPtr    pGC;
  780.   {
  781. !     struct finalSpan    **f;
  782. !     struct finalSpan    *span, *nextspan;
  783. !     DDXPointPtr        xSpans, xSpan;
  784. !     int            *xWidths, *xWidth;
  785. !     int            i;
  786. !     int            spany;
  787.   
  788.       if (nspans == 0)
  789.           return;
  790. --- 2295,2365 ----
  791.       int            min, max;    /* x values */
  792.   };
  793.   
  794. + static struct finalSpan    *freeFinalSpans, *tmpFinalSpan;
  795. + # define allocFinalSpan()   (freeFinalSpans ?\
  796. +                 ((tmpFinalSpan = freeFinalSpans), \
  797. +                  (freeFinalSpans = freeFinalSpans->next), \
  798. +                  (tmpFinalSpan->next = 0), \
  799. +                  tmpFinalSpan) : \
  800. +                  realAllocSpan ())
  801. + # define SPAN_CHUNK_SIZE    128
  802. + struct finalSpanChunk {
  803. +     struct finalSpan    data[SPAN_CHUNK_SIZE];
  804. +     struct finalSpanChunk    *next;
  805. + };
  806. + static struct finalSpanChunk    *chunks;
  807. + struct finalSpan *
  808. + realAllocSpan ()
  809. + {
  810. +     register struct finalSpanChunk    *newChunk;
  811. +     register struct finalSpan    *span;
  812. +     register int            i;
  813. +     newChunk = (struct finalSpanChunk *) Xalloc (sizeof (struct finalSpanChunk));
  814. +     if (!newChunk)
  815. +         return (struct finalSpan *) Xalloc (sizeof (struct finalSpan));
  816. +     newChunk->next = chunks;
  817. +     chunks = newChunk;
  818. +     freeFinalSpans = span = newChunk->data + 1;
  819. +     for (i = 1; i < SPAN_CHUNK_SIZE-1; i++) {
  820. +         span->next = span+1;
  821. +         span++;
  822. +     }
  823. +     span->next = 0;
  824. +     span = newChunk->data;
  825. +     span->next = 0;
  826. +     return span;
  827. + }
  828. + disposeFinalSpans ()
  829. + {
  830. +     struct finalSpanChunk    *chunk, *next;
  831. +     for (chunk = chunks; chunk; chunk = next) {
  832. +         next = chunk->next;
  833. +         Xfree (chunk);
  834. +     }
  835. +     chunks = 0;
  836. +     freeFinalSpans = 0;
  837. + }
  838.   fillSpans (pDrawable, pGC)
  839.       DrawablePtr    pDrawable;
  840.       GCPtr    pGC;
  841.   {
  842. !     register struct finalSpan    *span;
  843. !     register DDXPointPtr        xSpan;
  844. !     register int            *xWidth;
  845. !     register int            i;
  846. !     register struct finalSpan    **f;
  847. !     register int            spany;
  848. !     DDXPointPtr            xSpans;
  849. !     int                *xWidths;
  850.   
  851.       if (nspans == 0)
  852.           return;
  853. ***************
  854. *** 2177,2194 ****
  855.       i = 0;
  856.       f = finalSpans;
  857.       for (spany = finalMiny; spany < finalMaxy; spany++, f++) {
  858. !         for (span = *f; span; span=nextspan) {
  859. !             nextspan = span->next;
  860. !             if (span->max > span->min) {
  861. !                 xSpan->x = span->min;
  862. !                 xSpan->y = spany;
  863. !                 ++xSpan;
  864. !                 *xWidth++ = span->max - span->min;
  865. !                 ++i;
  866.               }
  867. !             Xfree (span);
  868.           }
  869.       }
  870.       Xfree (finalSpans);
  871.       (*pGC->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE);
  872.       Xfree (xSpans);
  873. --- 2368,2386 ----
  874.       i = 0;
  875.       f = finalSpans;
  876.       for (spany = finalMiny; spany < finalMaxy; spany++, f++) {
  877. !         for (span = *f; span; span=span->next) {
  878. !             if (span->max <= span->min) {
  879. !                 printf ("span width: %d\n", span->max-span->min);
  880. !                 continue;
  881.               }
  882. !             xSpan->x = span->min;
  883. !             xSpan->y = spany;
  884. !             ++xSpan;
  885. !             *xWidth++ = span->max - span->min;
  886. !             ++i;
  887.           }
  888.       }
  889. +     disposeFinalSpans ();
  890.       Xfree (finalSpans);
  891.       (*pGC->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE);
  892.       Xfree (xSpans);
  893. ***************
  894. *** 2200,2214 ****
  895.       nspans = 0;
  896.   }
  897.   
  898. ! # define SPAN_REALLOC    2048
  899.   
  900.   struct finalSpan **
  901. ! findSpan (y)
  902.   {
  903.       struct finalSpan    **newSpans;
  904.       int            newSize, newMiny, newMaxy;
  905. -     int            i;
  906.       int            change;
  907.   
  908.       if (y < finalMiny || y >= finalMaxy) {
  909.           if (y < finalMiny)
  910. --- 2392,2410 ----
  911.       nspans = 0;
  912.   }
  913.   
  914. ! # define SPAN_REALLOC    1024
  915.   
  916. + # define findSpan(y) ((finalMiny <= (y) && (y) < finalMaxy) ? \
  917. +               &finalSpans[(y) - finalMiny] : \
  918. +               realFindSpan (y))
  919.   struct finalSpan **
  920. ! realFindSpan (y)
  921.   {
  922.       struct finalSpan    **newSpans;
  923.       int            newSize, newMiny, newMaxy;
  924.       int            change;
  925. +     int            i;
  926.   
  927.       if (y < finalMiny || y >= finalMaxy) {
  928.           if (y < finalMiny)
  929. ***************
  930. *** 2234,2243 ****
  931.                      finalSize * sizeof (struct finalSpan *));
  932.               Xfree (finalSpans);
  933.           }
  934. !         for (i = newMiny; i < finalMiny; i++)
  935. !             newSpans[i-newMiny] = 0;
  936. !         for (i = finalMaxy; i < newMaxy; i++)
  937. !             newSpans[i-newMiny] = 0;
  938.           finalSpans = newSpans;
  939.           finalMaxy = newMaxy;
  940.           finalMiny = newMiny;
  941. --- 2430,2440 ----
  942.                      finalSize * sizeof (struct finalSpan *));
  943.               Xfree (finalSpans);
  944.           }
  945. !         if ((i = finalMiny - newMiny) > 0)
  946. !             bzero (newSpans, i * sizeof (struct finalSpan *));
  947. !         if ((i = newMaxy - finalMaxy) > 0)
  948. !             bzero (newSpans + finalMaxy - newMiny,
  949. !                    i * sizeof (struct finalSpan *));
  950.           finalSpans = newSpans;
  951.           finalMaxy = newMaxy;
  952.           finalMiny = newMiny;
  953. ***************
  954. *** 2247,2255 ****
  955.   }
  956.   
  957.   newFinalSpan (y, xmin, xmax)
  958.   {
  959. !     struct finalSpan    **f;
  960. !     struct finalSpan    *x, *oldx, *prev;
  961.   
  962.       f = findSpan (y);
  963.       oldx = 0;
  964. --- 2444,2456 ----
  965.   }
  966.   
  967.   newFinalSpan (y, xmin, xmax)
  968. + int        y;
  969. + register int    xmin, xmax;
  970.   {
  971. !     register struct finalSpan    *x;
  972. !     register struct finalSpan    **f;
  973. !     struct finalSpan        *oldx;
  974. !     struct finalSpan        *prev;
  975.   
  976.       f = findSpan (y);
  977.       oldx = 0;
  978. ***************
  979. *** 2269,2275 ****
  980.                       else
  981.                           *f = x->next;
  982.                       --nspans;
  983. -                     Xfree (x);
  984.                   } else {
  985.                       x->min = min (x->min, xmin);
  986.                       x->max = max (x->max, xmax);
  987. --- 2470,2475 ----
  988. ***************
  989. *** 2285,2291 ****
  990.               break;
  991.       }
  992.       if (!oldx) {
  993. !         x = (struct finalSpan *) Xalloc (sizeof (struct finalSpan));
  994.           x->min = xmin;
  995.           x->max = xmax;
  996.           x->next = *f;
  997. --- 2485,2491 ----
  998.               break;
  999.       }
  1000.       if (!oldx) {
  1001. !         x = allocFinalSpan ();
  1002.           x->min = xmin;
  1003.           x->max = xmax;
  1004.           x->next = *f;
  1005. ***************
  1006. *** 2318,2371 ****
  1007.       sppPoint->y = -sppPoint->y;
  1008.   }
  1009.   
  1010. ! mirrorSpan (quadrant, y, min, max)
  1011. !     double        y;
  1012. !     double        min, max;
  1013. ! {
  1014. !     int        spany, xmin, xmax;
  1015. !     double        t;
  1016.   
  1017. -     switch (quadrant) {
  1018. -     case 0:
  1019. -         break;
  1020. -     case 1:
  1021. -         t = -max;
  1022. -         max = -min;
  1023. -         min = t;
  1024. -         break;
  1025. -     case 2:
  1026. -         t = -max;
  1027. -         max = -min;
  1028. -         min = t;
  1029. -         y = -y;
  1030. -         break;
  1031. -     case 3:
  1032. -         y = -y;
  1033. -         break;
  1034. -     }
  1035. -     xmin = (int) ceil (min + arcXcenter) + arcXoffset;
  1036. -     xmax = (int) ceil (max + arcXcenter) + arcXoffset;
  1037. -     spany = (int) (ceil (arcYcenter - y)) + arcYoffset;
  1038. -     if (xmax > xmin)
  1039. -         newFinalSpan (spany, xmin, xmax);
  1040. - }
  1041.   static int    quadrantMask;
  1042.   
  1043. ! mergeSpan (y, min, max)
  1044. !     double    y, min, max;
  1045.   {
  1046. !     if (quadrantMask & 1)
  1047. !         mirrorSpan (0, y, min, max);
  1048. !     if (quadrantMask & 2)
  1049. !         mirrorSpan (1, y, min, max);
  1050. !     if (quadrantMask & 4)
  1051. !         mirrorSpan (2, y, min, max);
  1052. !     if (quadrantMask & 8)
  1053. !         mirrorSpan (3, y, min, max);
  1054.   }
  1055.   
  1056. ! static double    spanY;
  1057.   
  1058.   drawArc (x0, y0, w, h, l, a0, a1, right, left)
  1059.       int    x0, y0, w, h, l, a0, a1;
  1060. --- 2518,2577 ----
  1061.       sppPoint->y = -sppPoint->y;
  1062.   }
  1063.   
  1064. ! static double    spanY;
  1065.   
  1066.   static int    quadrantMask;
  1067.   
  1068. ! span (left, right)
  1069. !     double    left, right;
  1070.   {
  1071. !     register int    mask = quadrantMask, bit;
  1072. !     register double    min, max, y;
  1073. !     int    xmin, xmax, spany;
  1074. !     while (mask) {
  1075. !         bit = lowbit (mask);
  1076. !         mask &= ~bit;
  1077. !         switch (bit) {
  1078. !         case 1:
  1079. !             min = left;
  1080. !             max = right;
  1081. !             y = spanY;
  1082. !             break;
  1083. !         case 2:
  1084. !             min = -right;
  1085. !             max = -left;
  1086. !             y = spanY;
  1087. !             break;
  1088. !         case 4:
  1089. !             min = -right;
  1090. !             max = -left;
  1091. !             y = -spanY;
  1092. !             break;
  1093. !         case 8:
  1094. !             min = left;
  1095. !             max = right;
  1096. !             y = -spanY;
  1097. !             break;
  1098. !         default:
  1099. !             abort ();
  1100. !         }
  1101. !         xmin = (int) ceil (min + arcXcenter) + arcXoffset;
  1102. !         xmax = (int) ceil (max + arcXcenter) + arcXoffset;
  1103. !         spany = (int) (ceil (arcYcenter - y)) + arcYoffset;
  1104. !         if (xmax > xmin)
  1105. !             newFinalSpan (spany, xmin, xmax);
  1106. !     }
  1107.   }
  1108.   
  1109. ! /*
  1110. !  * split an arc into pieces which are scan-converted
  1111. !  * in the first-quadrant and mirrored into position.
  1112. !  * This is necessary as the scan-conversion code can
  1113. !  * only deal with arcs completely contained in the
  1114. !  * first quadrant.
  1115. !  */
  1116.   
  1117.   drawArc (x0, y0, w, h, l, a0, a1, right, left)
  1118.       int    x0, y0, w, h, l, a0, a1;
  1119. ***************
  1120. *** 2555,2560 ****
  1121. --- 2761,2770 ----
  1122.           drawQuadrant (&def, &acc, sweep[j].a0, sweep[j].a1, mask, 
  1123.                      passRight, passLeft);
  1124.       }
  1125. +     /*
  1126. +      * mirror the coordinates generated for the
  1127. +      * faces of the arc
  1128. +      */
  1129.       if (right) {
  1130.           mirrorSppPoint (rightq, &right->clock);
  1131.           mirrorSppPoint (rightq, &right->center);
  1132. ***************
  1133. *** 2611,2618 ****
  1134.       /*
  1135.        * add the pixel at the top of the arc
  1136.        */
  1137. !     if (a1 == 90 * 64 && (quadrantMask & 1) && ((int) (def->w * 2 + def->l)) & 1)
  1138. !         mirrorSpan (0, def->h + def->l/2, 0.0, 1.0);
  1139.   }
  1140.   
  1141.   max (x, y)
  1142. --- 2821,2831 ----
  1143.       /*
  1144.        * add the pixel at the top of the arc
  1145.        */
  1146. !     if (a1 == 90 * 64 && (mask & 1) && ((int) (def->w * 2 + def->l)) & 1) {
  1147. !         quadrantMask = 1;
  1148. !         spanY = def->h + def->l/2;
  1149. !         span (0.0, 1.0);
  1150. !     }
  1151.   }
  1152.   
  1153.   max (x, y)
  1154. ***************
  1155. *** 2625,2632 ****
  1156.       return x<y? x:y;
  1157.   }
  1158.   
  1159. - span (left, right)
  1160. - double    left, right;
  1161. - {
  1162. -     mergeSpan (spanY, left, right);
  1163. - }
  1164. --- 2838,2840 ----
  1165. -- 
  1166. Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
  1167. Moderator of comp.sources.x
  1168.